// @ts-nocheck
/**
 * @template T
 * @param {{(h: (x: T) => T): (x: T) => T}} f
 * @returns {(x: T) => T}
 */
function Y(f) {
  const g = f(
    ((h) => {
      (...args) => {
        const g = f(h(h));
        return g.apply(this, args);
      };
    })((h) => (...args) => {
      const g = f(h(h));
      return g.apply(this, args);
    }),
  );
  return g;
}

const fac = Y(
  (f) =>
    function (n) {
      return n > 1 ? n * f(n - 1) : 1;
    },
);
console.log(fac(5));

const fib = Y((f) => (n) => (n > 1 ? f(n - 1) + f(n - 2) : n));

console.log(fib(5));
